home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 July: Mac OS SDK / Dev.CD Jul 96 SDK / Dev.CD Jul 96 SDK2.toast / Development Kits (Disc 2) / QuickDraw GX / Programming Stuff / GX Libraries / SplineLibrary.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-04-07  |  3.8 KB  |  127 lines  |  [TEXT/MPS ]

  1.  
  2. /*
  3.     File:        SplineLibrary.c
  4.  
  5.     Contains:    graphics libraries - Spline generation routines
  6.     
  7.     Written by:    Cary Clark, Georgiann Delaney, Michael Fairman, Dave Good, Robert Johnson, Keith McGreggor, Oliver Steele, David Van Brink, Chris Yerga
  8.     
  9.     Copyright:    © 1995 by Apple Computer, Inc., all rights reserved.
  10.  
  11.     Change History (most recent first):
  12.  
  13.          <3>      4/7/95    jtd        changed 'fract' to 'Fract'
  14.          <2>      1/9/95    JD        changed 'boolean' to 'Boolean'
  15.          <1>      1/9/95    JD        First checked in.
  16. */
  17.  
  18. #include <Memory.h>
  19. #include "GraphicsLibraries.h"
  20.  
  21. enum { onCurvePoint, offCurvePoint };
  22.  
  23. typedef struct
  24. {   long count;
  25.     unsigned long mask;
  26.     long control;
  27.     long *bits;
  28.     gxPoint *points;
  29. } splineBuild;
  30.  
  31. static void BeginSplineBuild(splineBuild *build, long *bits, gxPoint *points)
  32. {
  33.     build->count = 0;
  34.     build->mask = 0;
  35.     build->control = 0;
  36.     build->bits = bits;
  37.     build->points = points;
  38. }
  39.  
  40. static void EndSplineBuild(splineBuild *build)
  41. {   
  42.     if (build->mask) *build->bits = build->control;
  43. }
  44.  
  45. static void AddPoint(splineBuild *build, gxPoint *add, Boolean offCurve)
  46. {
  47.     *build->points++ = *add;
  48.     if (build->mask == 0) build->mask = (-1UL >> 1) + 1;
  49.     if (offCurve) build->control |= build->mask;
  50.     if ((build->mask >>= 1) == 0)
  51.     {   *build->bits++ = build->control;
  52.         build->control = 0;
  53.     }
  54.     ++build->count;
  55. }
  56.  
  57. static void AddTangent(splineBuild *build, gxPoint *base, gxPoint *tangent, Fixed factor)
  58. {
  59.     gxPoint control;
  60.     control.x = base->x + FractMultiply(tangent->x, factor);
  61.     control.y = base->y + FractMultiply(tangent->y, factor);
  62.     AddPoint(build, &control, offCurvePoint);
  63. }
  64.  
  65. gxShape MirrorSpline(long count, gxPoint *points, Fract slack, Boolean closed)
  66. {
  67.     gxShape spline;
  68.     gxPoint *mine, *next;
  69.     Fixed prevLen, nextLen;
  70.     gxPoint prevDir, nextDir;
  71.     splineBuild build;
  72.     long actIndex, estCount = 3 * count, estIndex = 2 + (estCount + 31 >> 5);
  73.     long *storage = (long *)NewPtr(estIndex * sizeof(long) + estCount * sizeof(gxPoint));
  74.  
  75.     BeginSplineBuild(&build, storage + 2, (gxPoint *)(storage + estIndex));
  76.  
  77.     mine = next = points;
  78.     if (closed) mine += count - 1;
  79.     nextDir.x = next->x - mine->x;
  80.     nextDir.y = next->y - mine->y;
  81.     nextLen = Magnitude(nextDir.x, nextDir.y);
  82.     if (nextLen)
  83.     {   nextDir.x = FractDivide(nextDir.x, nextLen);
  84.         nextDir.y = FractDivide(nextDir.y, nextLen);
  85.     }
  86.  
  87.     while (count--)
  88.     {   mine = next;
  89.         if (count) ++next;
  90.         else if (closed) next = points;
  91.         prevLen = nextLen;
  92.         if (prevLen) prevDir = nextDir;
  93.         nextDir.x = next->x - mine->x;
  94.         nextDir.y = next->y - mine->y;
  95.         nextLen = Magnitude(nextDir.x, nextDir.y);
  96.         if (nextLen)
  97.         {   nextDir.x = FractDivide(nextDir.x, nextLen);
  98.             nextDir.y = FractDivide(nextDir.y, nextLen);
  99.             if (prevLen && slack)
  100.             {   gxPoint tangent;
  101.                 tangent.x = (prevDir.x >> 1) + (nextDir.x >> 1) >> 1;
  102.                 tangent.y = (prevDir.y >> 1) + (nextDir.y >> 1) >> 1;
  103.                 AddTangent(&build, mine, &tangent, -FractMultiply(slack, prevLen));
  104.                 if (nextLen != prevLen) AddPoint(&build, mine, onCurvePoint);
  105.                 AddTangent(&build, mine, &tangent, FractMultiply(slack, nextLen));
  106.             }
  107.             else goto addThis;
  108.         }
  109.         else if (!closed && count == 0)
  110.     addThis:    AddPoint(&build, mine, onCurvePoint);
  111.     }
  112.  
  113.     EndSplineBuild(&build);
  114.  
  115.     actIndex = 2 + (build.count + 31 >> 5);
  116.     if (actIndex < estIndex)
  117.         BlockMove(storage + estIndex, storage + actIndex, build.count * sizeof(gxPoint));
  118.     storage[0] = 1;
  119.     storage[1] = build.count;
  120.     spline = GXNewPaths((gxPaths *)storage);
  121.     if (closed) GXSetShapeFill(spline, gxClosedFrameFill);
  122.     else GXSetShapeFill(spline, gxOpenFrameFill);
  123.  
  124.     DisposePtr((Ptr)storage);
  125.     return spline;
  126. }
  127.